use chrono::{DateTime, Local};
use serde::Deserialize;
use validator::Validate;

use crate::{utils, Result};

#[derive(Deserialize, Validate, Default)]
#[serde(default)]
pub struct Add {
    #[validate(length(min = 10))]
    pub origin: String,
    pub password: String,
    pub expired: String,
}

impl Add {
    pub fn parsed_expired(&self) -> Result<DateTime<Local>> {
        if self.expired.is_empty() {
            Ok(utils::dt::default())
        } else {
            utils::dt::parse(&self.expired)
        }
    }
    pub fn has_expired(&self) -> bool {
        !self.expired.is_empty()
    }
    pub fn has_password(&self) -> bool {
        !self.password.is_empty()
    }
    pub fn hashed_password(&self) -> Result<String> {
        if self.password.is_empty() {
            return Ok("".into());
        }

        utils::password::hash(&self.password)
    }

    pub fn skip_update_password(&self) -> bool {
        &self.password == "-NO-CHANGED-"
    }
}

pub type Edit = Add;

#[derive(Deserialize, Validate, Default)]
#[serde(default)]
pub struct UserAdd {
    #[serde(flatten)]
    pub url: Add,

    #[validate(length(min = 36))]
    pub captcha: String,
}

#[derive(Deserialize, Validate, Default)]
#[serde(default)]
pub struct VisitCheckPassword {
    #[validate(length(min = 20, max = 20))]
    pub id: String,

    #[validate(length(min = 1))]
    pub password: String,
}

#[derive(Deserialize, Validate, Default)]
#[serde(default)]
pub struct List {
    #[serde(flatten)]
    pub p: super::Page,
}
